#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <mpi.h>
#include "md5_parallel.h"

int main(int argc, char* argv[])
{
	uint8_t *init_message;
	uint32_t *padded_message;
	uint32_t md5_result[4];
	uint64_t message_length;
	
	FILE *infile;
	struct stat buf;
	int i, rank, num_threads;
	
	MPI_Init(&argc,&argv);
	MPI_Comm_rank(MPI_COMM_WORLD,&rank);
	MPI_Comm_size(MPI_COMM_WORLD,&num_threads);
	
	if(rank == 0)
	{
		if(argc != 2)
		{
			printf("Usage: ./md5encrypt <filename>\n");
			exit(1);
		}
		
		infile = fopen(argv[1], "rb");
		
		if(infile == NULL)
		{
			printf("Could not open input file %s.\n",argv[1]);
			exit(1);
		}
				
		fstat(fileno(infile), &buf);
		
		message_length = buf.st_size;
		//message_length = 1;

		init_message = (uint8_t*)calloc(message_length,sizeof(uint8_t));
		fread((void*)(init_message),1,message_length,infile);
		
		/*if(init_message[message_length - 1] == '\n')
		{
			message_length--;
		}*/

		padded_message = pad_bits(init_message,&message_length);
		
		/*for(i = 0; i < message_length; i++)
		{
			printf("%.8x",padded_message[i]);
		}
		printf("\n");*/
	}
	MPI_Barrier(MPI_COMM_WORLD);
	MPI_Bcast(&message_length,1,MPI_UNSIGNED_LONG_LONG,0,MPI_COMM_WORLD);
	if(rank != 0)
	{
		padded_message = (uint32_t*)malloc(message_length*sizeof(uint32_t));
	}
	//MPI_Bcast(padded_message,message_length,MPI_UNSIGNED,0,MPI_COMM_WORLD);
	md5_encrypt(padded_message,message_length,md5_result,rank,num_threads);
	
	if(rank == 0)
	{
		for(i = 0; i < 4; i++)
		{
			printf("%08x",md5_result[i]);
		}
		printf("\n");
	
		free(padded_message);
		//free(init_message);
		fclose(infile);
	}
	
	MPI_Finalize();
	
	return 0;
}
